home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-10-11 | 82.0 KB | 2,311 lines |
- ------------------------------------------------------
- Dragonsmith Programmer╒s Manual (text format)
- ------------------------------------------------------
-
-
- version 1.1
- Sunday, October 11, 1992
- by Paul Hoffman
-
- ╥Dragons do not enter into this story╔╙
-
-
- Send bug reports, comments, and suggestions to:
-
- Mail Paul Hoffman
- 840 S. First, Apt.1
- Ann Arbor MI 48103
- U.S.A.
-
- Internet paul.hoffman@um.cc.umich.edu
-
- AFS /afs/umich.edu/user/n/k/nkuitse
-
-
- **************************************************
- * NOTE: *
- * *
- * This document is a text-only version of the *
- * file ╥Dragonsmith Programmer╒s Manual╙ *
- * *
- * The text is all the same, but a few tables *
- * and figures are missing from this file *
- * *
- **************************************************
-
- ------------------------------------------------------
- CONTENTS
- ------------------------------------------------------
-
- Introduction
- What is Dragonsmith?
- What is drag-and-drop, and what is it good for?
- How does the Finder know what can be drag-and-dropped where?
- What is a dragon, and why is it called that?
- What can Dragonsmith do, and what can╒t it do?
- Can I use Dragonsmith with System 6?
- Why use object-oriented programming (OOP)?
- Where can I find out more about OOP?
- Does Dragonsmith use the THINK╩Class Library?
- How do I create my own dragon?
- How do I upgrade from Dragonsmith v1.0b2 to v1.1?
- Will I have to rewrite my code when the next release of Dragonsmith comes out?
-
- Getting started
- Dragonsmith 1.1 files
- Upgrading from Dragonsmith 1.0b2
- PreDragon
- Creating the project file
- Creating the project resource file
- Writing a subclass of Dragon
- Compiling and debugging your dragon
-
- Program flow
-
- When something goes wrong╔
- Error ╘Can╒t open file ╥PreDragon╙╒
- Syntax error at the first line
- Link error ╘Undefined:╩CreateGDragon╒
- AEProcessAppleEvent returns error ╨608 (noOutstandingHLE)
- AEProcessAppleEvent returns error ╨609 (connectionInvalid)
- Your dragon won╒t drop (or it ╘overdrops╒)
- Your dragon crashes shortly after an Apple event is handled
-
- Notes on Apple events
-
- How to╔
- Automatic disk and folder opening
- Adding a menu
- Adding a preference setting
-
- Dragons ahoy!
-
- Dragon instance variables
-
- Dragon methods
-
- Resources
-
-
- ------------------------------------------------------
- INTRODUCTION
- ------------------------------------------------------
-
- What is Dragonsmith?
-
- Dragonsmith is an object-oriented framework for developing drag-and-drop
- applications under Macintosh System╩7.
-
- What is drag-and-drop, and what is it good for?
-
- The drag-and-drop feature of the System 7 Finder lets you open files using
- an application other than the one that created it. Here╒s a (rather
- simplistic) outline of how this works:
- Ñ The user drags a file╒s icon onto that of a drag-and-drop application
- Ñ The Finder launches the application (if it wasn╒t already running)
- Ñ The Finder sends the application an Apple event telling it to open the
- file
- Ñ The application opens the file
-
- How does the Finder know what can be drag-and-dropped where?
-
- As you drag a file╒s icon around the desktop, the Finder hilites an
- application icon the pointer passes over only if the application is capable
- of opening that type of file. (The situation is more complicated when you
- drag more than one icon at a time.) The Finder uses the desktop database to
- decide which applications can open which types of files; this information in
- turn comes from ╘FREF╒ resources found in the application files. Because
- the desktop database sometimes gets messed up (and out of a general sense of
- caution), applications developed with Dragonsmith do their own checking of
- ╘FREF╒ resources and file types.
-
- What is a dragon, and why is it called that?
-
- A dragon is an application that is driven primarily by drag-and-drop ╤ it
- doesn╒t do much if you double-click on its icon, but drop a few files on it
- and watch it go! Instead of ╘opening╒ drag-and-dropped files, dragons
- ╘process╒ them. This ╘processing╒ can be any type of action ╤ deleting a
- file, compiling an index of it, extracting sounds from its resource fork,
- etc. Here╒s a list of some dragon-and-drop applications and what they do:
-
- Alias Director 2.7 Creates aliases to files, folders, and disks.
- Alias Finder Opens the Finder window containing the original file or
- folder of an alias.
- FileTyper 3.0 Allows one to change the file type, creator, and other
- attributes of files.
- GroupInfo Displays the total amount of disk space used by a group
- of files and folders.
- Paradigma 2.0 Finds and replaces strings in a text file.
- Save a BNDL Refreshes a file╒s BNDL information to update its icons,
- etc. in the Finder.
- StuffIt Expander¬ Expands StuffIt and CompactPro archives and AppleLink
- packages.
- Text Merger 1.02 Merges several text files into a single file.
-
- There is a great deal of variety among these applications (and others like
- them). Some of them will accept drag-and-dropped folders or disks in
- addition to files. Some process files quietly and quit automatically when
- they╒re done; others stick around to give you the opportunity to change
- settings. Some only run in System 7; others will run in System 6, using the
- Standard File routines to choose the files you want to process. The
- important thing is what they all have in common ╤ drag-and-drop ╘batch╒
- processing of files.
-
- Why the name dragon?
-
- Ñ Dragons are drag-and-dropped on (of course).
- Ñ Dragons are distant cousins of UNIX daemons (which, strangely enough, do
- their thing in the wings).
- Ñ Dragons have been known to enter (quite uninvited) into the stories of a
- certain amateur writer.
-
- What can Dragonsmith do, and what can╒t it do?
-
- Dragonsmith can be used to create any application, but it wouldn╒t make
- sense to develop one that didn╒t feature drag-and-drop prominently. There
- wouldn╒t be much point, for example, in using Dragonsmith to make a word
- processor ╤ it would be more suited for an application that displays the
- total number of words and paragraphs in a group of text files dropped on it.
-
- Because most dragons will probably perform simple tasks, Dragonsmith has
- been designed with simplicity in mind. A simple Dragonsmith-produced
- application typically requires only about 20╨25K of disk space and runs in
- 40╨50K of memory. Because of the object-oriented nature of the Dragonsmith
- kit, however, advanced features can easily be added to a dragon.
-
- On the other hand, dragons developed with Dragonsmith have several more or
- less advanced capabilities:
-
- Preferences
- Automatic resource-based preferences file management is built
- into all dragons. Any dragon that you create can store, alter, and retrieve
- any number of preferences. The user can ask a dragon to use any particular
- preferences file that belongs to it by double-clicking on that file in the
- Finder. As long as you╒re careful to program defensively, the dragon will
- still run normally if a preferences file could not be found or created.
-
- Folder searching
- You can specify that folders and disks will automatically
- be opened recursively to any desired depth in search of files to be
- processed.
-
- Alias resolution
- If folder searching is enabled, then any alias files
- encountered may (optionally) be automatically resolved.
-
- Safe file handling
- A dragon will ╥see╙ only those documents (files, folders,
- and volumes) that the Finder would allow the user to drag-and-drop on it.
- If the dragon looks inside a folder dropped on it, or if it receives an Open
- Documents event from a source other than the Finder, it will ignore any
- files it doesn╒t know what to do with.
-
- Smart file filtering
- A dragon can easily be made to process only files that
- match specific criteria besides just the file type ╤ name, size, creator,
- location, etc.
-
- Background processing
- A dragon will run quietly in the background if the
- user decides to switch to (or launch) another application after dropping
- files on it; the dragon will take as much or as little CPU time away from
- other applications as you want it to.
-
- Apple event queuing
- The user can drag-and-drop documents on a dragon (or
- another Apple-event-savvy application can send the dragon an Open Documents
- event) while the dragon is busy at work on something else ╤ each batch of
- documents will be processed in the order in which it was received.
-
- Auto-quit
- You can specify that a dragon will automatically quit after
- processing drag-and-dropped documents (or if double-clicked in the Finder).
-
- Environment checking
- A dragon will terminate gracefully if launched in a
- run-time environment insufficient for its needs ╤ and the specifications for
- its run-time requirements can be changed without any source code
- modifications.
-
-
- The following features are not supported by Dragonsmith 1.1 but are under
- consideration for future releases:
-
- Apple Event objects
- Adding Apple Event Object Model and scripting support is
- a high priority. This will enable control of dragons by Apple event-savvy
- applications, including scripting environments like UserLand Frontier and
- the forthcoming AppleScript. A small Dragon suite of custom Apple events is
- a possibility.
-
- Improved error handing
- The Dragon class╒s error handling capability is
- currently rudimentary. Improvements will include better reporting of errors
- to the user and, when Apple Event Object support is added, to client
- applications.
-
- Progress window
- Also in the works is a movable modal dialog to show what
- documents are being processed, display error messages, etc.
-
- More sophisticated preferences handling
- There is currently no support in the Dragon and Preferences classes for
- preferences file ╘Open,╒ ╘Save╒ and ╘Save As╔╒ operations. These
- capabilities should form part of a general preferences-editing interface ╤
- perhaps via a ╘Preferences╔╒ item added to the ╘Edit╒ menu.
-
- Drakelings
- There is a growing trend in the Macintosh world toward
- ╘miniature╒ custom stand-alone drag-and-drop applications created by a
- ╘master╒ application ╤ Frontier╒s applets belong to this category, as do the
- ╘ParaDoids╒ created by Espen Aarseth╒s excellent Paradigma, and the
- ╘AutoTypers╒ in Daniel Azuma╒s FileTyper package. Implementing this type of
- document-application hybrid in Dragonsmith is a high priority.
-
- Faceless dragons
- Some dragons don╒t need any user interface. The Dragon
- class currently uses an instance variable autoQuit to designate that a
- dragon will quit immediately after receiving the first Open Documents event
- it receives. A better solution, however, would be a simpler class (of which
- Dragon would become a subclass) designed for creating background-only
- dragons. This could significantly reduce the size of simple faceless
- dragons, which is especially important in light of the interface
- enhancements planned for the Dragon class.
-
- FilterTop support
- The freeware FilterTop project currently under development
- will provide a programming framework similar in some ways to that of
- Dragonsmith. FilterTop is likely to garner a good deal of popularity, and
- Dragonsmith and it should be able to complement each other very nicely.
-
- Can I use Dragonsmith with System 6?
-
- No, System 7 is required. The whole point of dragons is defeated in a
- no-drag-and-drop, no-Apple-events environment.
-
- Why use object-oriented programming (OOP)?
-
- The center of Dragonsmith╒s drag-and-drop framework is provided the Dragon
- class. To write your own dragon, you╒ll create a new subclass of Dragon
- that ╘inherits╒ the bulk of its code. Using OOP, you can easily override or
- extend Dragon╒s behavior without altering any source files ╤ you can change
- as much or as little as you need to.
-
- Where can I find out more about OOP?
-
- You might begin by reading parts of the THINK╩C Object-Oriented Programming
- Manual (for THINK╩C╩5.0). Pages 19╨24 and 28╨51 are a good starting point,
- and pages 81╨86 contain some information specific to using OOP in THINK╩C.
-
- Does Dragonsmith use the THINK╩Class Library?
-
- No. For most drag-and-drop applications, the TCL is overkill ╤ it contains
- a vast amount of code that most dragons will never need.
-
- On the other hand, you could use the TCL ╤ using code from Dragon.c, write a
- subclass of CApplication called CDragonApp or some such. It shouldn╒t be
- overwhelmingly difficult.
-
- [Remember, the source code in Dragonsmith may be freely altered and used for
- any purpose, subject only to the restrictions mentioned at the beginning of
- each file. Applications developed using Dragonsmith may be sold or given
- away without restriction.]
-
- How do I create my own dragon?
-
- The easiest way is to base your dragon on one of the template classes
- provided. Each of these files has step-by-step instructions on how to use
- it to write your own dragon:
-
- PlainTmpl.c A very simple ╘auto-quit╒ dragon without any interface
- MenusTmpl.c A simple dragon with an added menu
- PrefsTmpl.c A simple dragon with an added menu and preferences settings
-
- You might also want to read the source code files for the finished dragons
- provided with this release of Dragonsmith ╤ DFileCleaver.c, DFilePaths.c,
- and DPasser.c
-
- How do I upgrade from Dragonsmith v1.0b2 to v1.1?
-
- Follow the instructions in the Getting Started section below. The basic
- steps are:
-
- Ñ Replace the old Dragonsmith.╣ with the one in this release. You can
- throw away Dragonsmith.debug.╣ ╤ it╒s no longer needed.
-
- Ñ Move the bulk of your ProcessDroppings method to ProcessFile (and
- possibly move some to the BeginProcessing and EndProcessing methods) ╤ this
- may require adding a few instance variables. Your dragon will no longer
- need to directly access the data in the Open Documents event.
-
- Ñ If your dragon added any menus, rewrite its SetUpMenus and DoMenu methods
- and remove its basic Apple, File, and Edit menu functionality ╤ they╒re now
- implemented in Dragon.
-
- Ñ Change your dragon╒s signature from ╘Drgn╒ to some other unique value, if
- you hadn╒t already.
-
- Ñ Add some resources to your project╒s resource file.
-
- Ñ Recompile all the files in your project.
-
- Will I have to rewrite my code when the next release of Dragonsmith comes
- out?
-
- Hopefully not. This manual will warn you about certain features of the
- Dragon class that, for future compatibility, are best left alone. Still,
- the most important thing is to get the most out of the functionality already
- in the Dragon class ╤ future incompatibility dangers shouldn╒t inhibit you
- more than a little.
-
-
- ------------------------------------------------------
- GETTING STARTED
- ------------------------------------------------------
-
- Dragonsmith 1.1 files
-
- Dragonsmith
- ! Read me
- Base files <Normally, you shouldn╒t add to this folder or alter the files
- in it ╤ if you use a copy of one of these files, move it up into
- the Dragonsmith folder>
- Classes
- AppleEventQueue.c
- AppleEventQueue.h
- Preferences.c <A resource-based preferences management class that
- may be used outside of Dragonsmith>
- Preferences.h
- DFileCleaver.c
- DFilePaths.c
- DPasser.c
- Dragon.c <Code for the Dragon class>
- Dragon.h
- Dragonsmith TMPLs <ResEdit templates for editing custom resource types used
- in Dragonsmith>
- Dragonsmith.╣ <Use a copy of this project file with your code added for
- greater debugging control than is provided by (a copy of) Template.╣>
- FileCleaver.╣
- FileCleaver.╣.rsrc
- FilePaths.╣
- FilePaths.╣.rsrc
- Main.c <Contains the function main used for all dragons>
- Passer.╣
- Passer.╣.rsrc
- PreDragon.c <Source for the PreDragon precompiled headers file used by
- Dragonsmith projects>
- Utilities <Source code containing various utility functions>
- [numerous files]
- Documentation
- ! Release notes
- Dragonsmith Programmer╒s Manual
- Dragonsmith Manual (text) <This file>
- Preferences class notes
- Dragons
- ! Read Me (Dragons)
- File Cleaver 1.1
- File Paths 1.1 <Used to produce this list of files>
- Passer 1.1 <A dragon that passes Open Documents events to high level
- event-aware processes ╤ vital for debugging Apple event-handling code in the
- THINK╩C Debugger>
- Template files <Source code and resource template files for three simple
- kinds of Dragon subclass>
- DMenusTmpl.c
- DPlainTmpl.c
- DPrefsTmpl.c
- MenusTmpl.╣.rsrc
- PlainTmpl.╣.rsrc
- PrefsTmpl.╣.rsrc
- Template.╣ <Project file to copy and use with the template files>
-
- Upgrading from Dragonsmith 1.0b2
-
- The original release of Dragonsmith was much more simplistic. Processing of
- documents was treated as a single step ╤ the dragon developer was required
- to write (in ProcessDroppings) a loop to extract, then process, each
- document from the Open Documents Event. Any desired filtering of documents
- (treating files and folders differently, resolving alias files, opening only
- files of a certain type, etc.) had to be done by the subclass of Dragon.
- Programmers who needed file information were responsible for calling
- PBGetCatInfo themselves. In Dragonsmith 1.1, most of this ╘grunt╒ work is
- done for you by the Dragon class.
-
- The changes in functionality have brought about several significant changes
- in the Dragon class iinterface, and all Dragon 1.0b2 subclasses will have to
- be modified to work with Dragon 1.1.
-
- ProcessDroppings
-
- In Dragonsmith 1.0b2, every Dragon subclass had to override
- ProcessDroppings. In version 1.1, that╒s no longer true. In general,
- ProcessFile (and possibly ProcessDirectory) should be overridden;
- ProcessDroppings should not.
-
- To update your dragon to Dragonsmith 1.1, you╒ll probably move most of the
- code from your ProcessDroppings method to ProcessFile ╤ though some of it
- may need to go into BeginProcessing and EndProcessing. Updating your dragon
- will probably also require changing a few local variables in your old
- ProcessDroppings method to instance variables.
-
- In addition, ProcessDroppings╒ parameters have changed. The docs parameter
- isn╒t needed any more because information about the current file or
- directory is always accessible in *curDocFSS (an FSSpec record) and
- *curDocPB (a multi-purpose parameter block subsuming the HParamBlockRec,
- CInfoPBRec, and other low-level File Manager param-blocks). The numDocs
- parameter has no counterpart in Dragon 1.1 ╤ a more sophisticated file
- counting and tracking mechanism is planned for a future version of
- Dragonsmith.
-
- Menus
-
- The new Dragon class implements standard Apple and Edit menus, plus a File
- menu with a single Quit item. The DFilePaths class released as part of
- Dragonsmith 1.0b2 used a different means to implement essentially the same
- menus ╤ any dragons modeled after it will need to be changed to adhere to
- Dragon 1.1╒s menu scheme. Look at the DMenusTmpl.c file for an example of
- how a dragon should add menus.
-
- Signatures and the Desktop Manager
-
- Dragonsmith 1.0b2 didn╒t make it clear that every new dragon should have a
- unique application signature (and, for clarity, a distinct icon in the
- Finder). If more than one application in your Mac work environment has the
- same signature, then drag-and-drop for either of them (or both) may not work
- properly. You are encouraged to assign your dragons unique signatures and
- register each one with Apple.
-
- PreDragon
-
- One of the first things you should do is to make a precompiled headers file
- from PreDragon.c. The resulting file should be named PreDragon and placed
- in the Base Files folder. The source files in the Dragonsmith kit all rely
- on these precompiled headers.
-
- Creating the project file
-
- Start with a copy of Template.╣ (or a copy of Dragonsmith.╣ if you want more
- control over debugging), then add the file which holds the source code for
- your dragon. The code for a simple dragon will most likely fit into a
- single segment, not counting extra segments (such as ╘CODE╒ 0) that THINK╩C
- creates transparently.
-
- Make sure you choose ╘Set Project Type╔╒ from THINK╩C╒s Project menus and
- set the appropriate values for Creator (signature), partition, and SIZE
- flags.
-
- Creating the project resource file
-
- In general, you should start with a copy of one of the ╔Tmpl.╣.rsrc files
- and make modifications as necessary. The first changes you make should be
- in ╘STR╩╒ 128, the ╘FREF╒ resources, and ╘DrPr╒ 128. The Resources section
- in this document and the source files in the ╘Template Files╒ folder contain
- descriptions of the various resources used by Dragonsmith, as well as
- information on which resources to change and how.
-
- Writing a subclass of Dragon
-
- It╒s recommended that you start with one of the template classes provided in
- the ╘Template Files╒ folder. Information on how to make a dragon this way
- is provided in the source files. If you had previously developed a dragon
- using Dragonsmith 1.0b2, you should read the section Upgrading from
- Dragonsmith 1.0b2 above. For tips on adding specific functionality to your
- dragon, refer to the section How To╔ below.
-
- Constructor method
-
- Your dragon should use a constructor (a method with no return-value, whose
- name is that of the class to which it belongs) to initialize any instance
- variables it adds. Your dragon╒s constructor will be executed (immediately
- after the Dragon class╒s constructor) when the gDragon object is made in
- CreateGDragon. It should set any default instance variable values that you
- want to be different from the values assigned in Dragon::Dragon. If your
- dragon implements any custom preferences resources, you should add instance
- variables to hold their values and your constructor should set defaults for
- them (in case the ReadPrefs method fails).
-
- ProcessFile and ProcessDirectory
-
- These are the two most important methods ╤ without overriding one or both of
- them, your dragon won╒t do anything. If your dragon makes simple changes to
- a file or directory╒s catalog information, it can use the macros described
- below (curFileType, curDocCreated, etc.) to change the appropriate fields in
- curDocPB, then (at the end of ProcessFile or ProcessDirectory) call the
- SaveDocInfo method to have the information changed on disk. For more
- information, see Macros below and read the notes for SaveDocInfo in the
- Methods section.
-
- CreateGDragon
-
- This function is not defined in Dragon.c ╤ the code for it must be found in
- one of your dragon╒s source files. It performs the very important task of
- creating a dragon object of the desired Dragon subclass, and can be written
- as simply as this:
-
- Dragon *CreateGDragon (void)
- {
- return (Dragon *) new DMyDragonClass;
- }
-
- Compiling and debugging your dragon
-
- Passer
-
- Drag-and-drop is at the heart of dragons, so you╒ll need a way to debug your
- dragon╒s ProcessFile method (and related code). Unfortunately, there╒s no
- way to drag-and-drop files onto your dragon while it╒s running in the
- THINK╩C Debugger. Instead, you╒ll have to use the ╘Passer╒ dragon provided
- with Dragonsmith 1.1 to transmit Open Documents events to your dragon while
- it╒s being debugged. To do so, choose ╘Run╒ from the Project menu in
- THINK╩C, then start up Passer and choose ╘Target╔╒ from its Options menu.
- Once you╒ve selected your dragon╒s process from the resulting PPCBrowser
- dialog, any Open Documents events sent to Passer will simply be rerouted to
- your dragon without modification. Set a breakpoint in ProcessFile (or
- ProcessDirectory) to ╘catch╒ the event, then debug from there.
-
- Apple events and the THINK╩C Debugger
-
- While running your dragon in the THINK╩C Debugger, you must be careful not
- to set any breakpoints in code executed between a call to WaitNextEvent that
- returns a high-level event and the call to AEProcessAppleEvent that
- dispatches the event to the appropriate Apple event handler. You can set
- breakpoints in the handler itself and in the Dragon method it calls. If you
- forget this and set a breakpoint in the wrong place, AEProcessAppleEvent
- will return a noOutstandingHLE (╨608) error and the event will not be
- dispatched. Presumably this is due to a time-out internal to the Apple
- Event Maneger package (╘PACK╒ 8), because it seems to happen whether the
- source of the event specifies a time-out value or not.
-
- If you want to send yourself an Apple event, use the kCurrentProcess
- constant instead of sending by signature ╤ your signature under the THINK╩C
- Debugger is ╘KAHL╒ and THINK╩C or the THINK╩C Debugger may intercept the
- event.
-
- Don╒t set any breakpoints between a call to WaitNextEvent that returns a
- high-level event and the ensuing call to AEProcessAppleEvent. Otherwise,
- the Apple event will time out and AEProcessAppleEvent will return ╨608
- (noOutstandingHLE). This may also be true of AcceptHighLevelEvent ╤ it
- hasn╒t been tested.
-
-
-
- ------------------------------------------------------
- PROGRAM FLOW
- ------------------------------------------------------
-
- Figure 1 shows the flow of execution of a dragon as it starts up and
- subsequently receives an Open Documents event:
-
- <Figure 1 omitted>
-
- The main event loop in Dragon is essentially the same as that in almost any
- Macintosh application. For each event returned by WaitNextEvent, the
- DoEvent method calls the appropriate event-handling method ╤ DoMouseDown,
- DoSuspend, DoResume, DoKeyDown, etc. When an Open Documents event is
- received by your dragon, DoEvent calls DoHighLevelEvent, which dispatches
- the event to HandleOdoc, the Open Documents handler installed in the
- InitAppleEvents method. HandleOdoc in turn sends a DoOdoc message to
- gDragon, the global dragon object. DoOdoc extracts the event╒s
- keyDirectObject parameter (the list of documents to open) and uses it as a
- parameter to ProcessDroppings, which calls ProcessDoc for each document in
- the list.
-
- Things can get considerably more complicated than this diagram shows:
-
- Ñ When dirDepthLimit < 0 and ProcessDoc encounters a directory,
- ProcessDocsInDirectory will be executed instead of ProcessFile or
- ProcessDirectory, and recursion back to ProcessDoc will probably occur.
-
- Ñ The ProcessOwnedFile method will be called instead if your dragon is
- asked to open a file that belongs to it (i.e., one whose creator code is
- your dragon╒s signature). Typically, this is a preferences file, but a
- Dragon subclass might use this feature for other things ╤ to implement
- script files, for example.
-
- Ñ If a document your dragon is asked to open is of a type that it doesn╒t
- ╘know about╒ (i.e., that is not covered by its ╘FREF╒ resources), or if the
- document is rejected by CustomFilterDoc, then ProcessDoc will not be
- executed.
-
- Ñ If the dragon is busy processing something when an Open Documents event
- is received, DoOdoc will call SuspendAEvent instead of ProcessDroppings.
- This will add the event to a queue for later processing ╤ the event will be
- ╘on hold╒ until all preceding ╘odoc╒ events have been processed. The next
- time WaitNextEvent fails to return an event, Run will call ResumeAEvent to
- complete handling of the event. This way, all Open Documents events will be
- processed in the order in which they were received. Note that when a Quit
- Application event is received, any suspended events will return an error to
- the sending process and will not result in any documents being processed.
-
-
- ------------------------------------------------------
- WHEN SOMETHING GOES WRONG╔
- ------------------------------------------------------
-
- Error ╘Can╒t open file ╥PreDragon╙╒
-
- Either you haven╒t created the PreDragon precompiled headers file from
- PreDragon.c, or it╒s located where THINK╩C can╒t find it. See Creating your
- dragon skeleton above for more information.
-
- Syntax error at the first line
-
- The problem may be with your project prefix ╤ it should end with the line
-
- #include "PreDragon"
-
- Choose ╘Options╔╒ from THINK╩C╒s Edit menu to bring up a dialog where you
- can set this. You should not #include <MacHeaders> in the project prefix.
-
- Link error ╘Undefined:╩CreateGDragon╒
-
- You╒ve forgotten to define (write the code for) the CreateGDragon function.
- It should create an instance of your Dragon subclass (not of Dragon) and
- return a reference to the object, like this:
-
- Dragon *CreateGDragon (void)
- {
- return (Dragon *) new DMyDragonClass;
- }
-
- AEProcessAppleEvent returns error ╨608 (noOutstandingHLE)
-
- You may have set a breakpoint between the WaitNextEvent call that obtained
- the event and the AEProcessAppleEvent call that dispatched to your handler ╤
- see Compiling and debugging your dragon above for more information on using
- the THINK╩C Debugger.
-
- It is safe to set a breakpoint in your Apple event handler, or in the code
- that it calls (DoOapp, DoOdoc, DoPdoc, or DoQuit).
-
- AEProcessAppleEvent returns error ╨609 (connectionInvalid)
-
- You may have forgotten to set the ╘high level event aware╒ flag in your
- project╒s ╘SIZE╒ resource. Both the sender and receiver of a high-level
- event must have this flag set.
-
- Your dragon won╒t drop (or it ╘overdrops╒)
-
- If this is the first time you╒ve built your dragon, check to make sure that
- you╒ve given it a unique signature and not ╘????╒ (or ╘Drgn╒ ╤ Dragonsmith
- v1.0b2 implied that you should use this value).
-
- If you╒ve built it before, then there may be a problem with the desktop
- database. Delete any obsolete versions of your dragon that accepted
- different types (or move them to a floppy disk) and rebuild the desktop.
- (The utility application ╘Save a BNDL╒ may let you avoid this step ╤ but use
- it with caution.)
-
- Your dragon crashes shortly after an Apple event is handled
-
- Your Apple event may be returning an invalid error code. Make sure it
- returns an error listed in Inside Macintosh VI. It╒s not clear why this
- would cause a bus error, but it seemed to do so in an early version of
- Dragonsmith.
-
-
- ------------------------------------------------------
- NOTES ON APPLE EVENTS
- ------------------------------------------------------
-
- Any application which is high level event aware will receive exactly one of
- the three following kinds of events when launched by the Finder:
-
- Open Application
- If this event is received, the user double-clicked on the
- application in the Finder, or selected the application and chose ╘Open╒ from
- the File menu.
-
- Open Documents
- If this event is received, the user double-clicked on a file
- (or group of files) belonging to the application, or selected the file(s)
- and chose ╘Open╒ from the File menu, or drag-and-dropped it (or them) onto
- the application╒s icon.
-
- Print Documents
- If this event is received, the user selected a file (or
- group of files) and chose ╘Print╒ from the File menu.
-
- An application may receive any number of Open Documents and Print Documents
- from the Finder after it has started.
-
- Other processes may launch an application with any kind of Apple event, or
- none at all, and may later send any kind and number of Apple events to it.
- Because of this, your code should never rely on receiving any Apple events
- in any sequence.
-
- QuitApplication
- The Finder will send a Quit Application event to an
- application if the user chooses ╘Restart╒ or ╘Shut Down╒ from the ╘Special╒
- menu (and possibly under other circumstances as well). Other processes may
- send this event to the application at any time.
-
-
- ------------------------------------------------------
- HOW TO╔
- ------------------------------------------------------
-
- Automatic disk and folder opening
-
- To make your dragon automatically process files inside directories (i.e.,
- volumes and folders), change the value of dirDepthLimit (in your constructor
- as well as in the ╘DrPr╒ 128 resource) to a negative number indicating how
- many levels down your dragon will look. This feature can be very handy, but
- it can also be very dangerous. To avoid stack overflow, you should not set
- dirDepthLimit to a value less than about -100. If you set resolveAliases =
- TRUE, then the possibility of recursion becomes an issue.
-
- Figure 2 shows a hierarchical view of the contents of a folder
- ╘Miscellaneous╒ ╤ the depth of each file or folder (except 0 Another File
- alias) is indicated by the number its name begins with. How your dragon
- should set its instance variables (and the corresponding values in its
- ╘DrPr╒ 129 resource) depends on what action you want it to take when the
- user drag-and-drops the hilited files on it. (For the sake of this example,
- it╒s assumed that your dragon has ╘FREF╒ resources for types ╘fold╒ and
- ╘TEXT╒ and that all the files pictured are text files.)
-
- <Figure 2 omitted>
-
- Table 1 gives details on which combinations of values will result in a
- particular set of documents being processed. In several cases, the value of
- one or two instance variables is irrelevant.
-
- <Table 1 omitted>
-
- Adding a menu
-
- Refer to the file ╘MenusTmpl.c╒ for a simple illustration of how to add
- menus to your dragon. The information below on adding a preferences setting
- also shows how to add a menu.
-
- Adding a preference setting
-
- The ╘PrefsTmpl.c╒ file contains sample code showing you how to implement
- preferences in Dragonsmith. By default, every dragon will use a preferences
- file, whether it needs it or not ╤ to prevent your dragon from finding or
- creating a preferences file, put a null string in the ╘STR ╒ 128 resource
- and remove the ╘FREF╒ resource for the type designated by the instance
- variable prefsFileType.
-
- The ╘PrRo╒ 128 resource in your dragon╒s preferences (and application) file
- contains references to the preferences resources which belong to it. The
- first resource designated in the ╘PrRo╒ 128 resource must be ╘DrPr╒ 128,
- which contains several important values used by every Dragon subclass (see
- below).
-
- Documentation for the Preferences class is minimal in this release of
- Dragonsmith ╤ a later release will correct that. In the mean time, reading
- the source code for the class may be instructive.
-
- The steps involved in adding a new preference to your dragon are as follows:
-
- Ñ Add a resource in your project resource file to hold the preferences
- value(s)
-
- Ñ Create an entry for the added preferences resource at the end of the
- ╘PrRo╒ 128 resource in your project resource file
-
- Ñ Add an instance variable to hold a handle to the added resource
-
- Ñ Add instance variables to your Dragon subclass to hold the values from
- your added resource
-
- Ñ In your dragon╒s constructor method, initialize the preferences instance
- variables to safe, if-all-else-fails default values ╤ your dragon should not
- crash or abort if some preferences couldn╒t be found
-
- Ñ Override ReadPrefs as indicated below
-
- Ñ Add some way in your dragon╒s interface to change the additional
- preference(s)
-
- Ñ Add code to change the preferences resource in memory and save it to disk
-
- As an example, take the case of a dragon (named ╘Scruncher╒) that uses one
- of three compression methods (Fast, Normal, or Tight) to compact files. The
- user can choose any one of the three, and may also specify whether Finder
- information about the file is preserved in the resulting archive. These
- preferences are stored in a ╘ScPr╒ 128 resource in the Scruncher.╣.rsrc
- file. Figure 3 shows the dragon╒s added menu:
-
- <Figure 3 omitted>
-
- The DScruncher.c file would look something like this:
-
- #include "Dragon.h"
- #include ╥MenuUtils.h╙
- #include ╥Preferences.h╙
- #define prefScruncherPrefs prefDragonPrefs + 1
- enum {
- mOptions = mEdit + 1
- };
- enum {
- iFastScrunching,
- iNormalScrunching,
- iSmallScrunching,
- iLine3,
- iSaveFInfo
- };
-
- typedef struct {
- char scrunchType;
- Boolean saveFInfo;
- } ScrunchOpts;
-
- class DScruncher : public Dragon {
-
- protected:
- ScrunchOpts **scrunchOptions;
- char scrunchType;
- Boolean saveFInfo;
-
- public:
- DScruncher (void); // Constructor
-
- protected:
- [Protected method declarations omitted for brevity]
- };
-
- Dragon *CreateGDragon (void)
- {
- return (Dragon *) new DScruncher;
- }
-
- DScruncher::DScruncher (void)
- {
- optionsMenu = NULL;
- scrunchOptions = NULL;
- scrunchType = iNormalScrunching;
- saveFInfo = TRUE;
- }
-
- void DScruncher::ReadPrefs (void)
- {
- inherited::ReadPrefs ();
-
- scrunchOptions = (ScrunchOpts **) preferences->GetPrefResource
- (prefFilePathOptions);
-
- if (scrunchOptions != NULL) {
- HNoPurge ((Handle) scrunchOptions);
- scrunchType = scrunchOptions->scrunchType;
- saveFInfo = scrunchOptions->saveFInfo;
- }
- }
-
- void DScruncher::SetUpMenus (void)
- {
- inherited::SetUpMenus (); // Add the Apple, File, and Edit menus
-
- optionsMenu = GetMenu (mOptions);
- InitOptionsMenu ();
- InsertMenu (optionsMenu, 0);
-
- DrawMenuBar ();
- }
-
- void DScruncher::InitOptionsMenu (void)
- {
- // Initialize options menu (and set the options while we╒re at it)
- CheckItem (optionsMenu, iSaveFInfo, saveFInfo);
- SetScrunchType (iFastScrunching + scrunchType - 1);
- }
-
- void DScruncher::DoMenu (long menuItemCode)
- {
- if (menuItemCode >> 16 == mOptions)
- DoOptionsMenu (menuItemCode & 0xFFFF);
- else
- inherited::DoMenu (menuItemCode);
- }
-
- void DScruncher::DoOptionsMenu (short itemNum)
- {
- if (itemNum == iSaveFInfo)
- ToggleSaveFInfo ();
- else
- SetScrunchType (itemNum);
-
- // Save any changes that might have been made
- preferences->SavePrefResource (prefFilePathOptions);
- }
-
- void DScruncher::ToggleSaveFInfo (void)
- {
- saveFInfo = ToggleMenuItem (optionsMenu, iSaveFInfo);
- if (scrunchOptions)
- (*scrunchOptions)->saveFInfo = saveFInfo;
- }
-
- void DScruncher::SetScrunchType (short scrunchItem)
- {
- CheckOne (optionsMenu, iFastScrunching, iSmallScrunching, scrunchItem);
- scrunchType = scrunchItem;
- if (scrunchOptions)
- (*scrunchOptions)->scrunchType = scrunchType;
- }
-
- void DFilePaths::AdjustMenusBusy (void)
- {
- inherited::AdjustMenusBusy ();
- DisableItem (optionsMenu, 0); // Disable the Options menu
- }
-
- void DFilePaths::AdjustMenusIdle (void)
- {
- inherited::AdjustMenusIdle ();
- EnableItem (optionsMenu, 0); // Enable the options menu
- }
-
-
- ------------------------------------------------------
- DRAGONS AHOY!
- ------------------------------------------------------
-
- Here╒s a list of some dragons that have been spotted by the author on the
- (albeit distant) horizon:
-
- Drawk
- ╘Load╒ an awk program, then drag-and-drop input files.
-
- D. D. Rex
- Specify text substitutions using grep syntax, then drag-and-drop
- files to make the changes in ╤ something like Paradigma, but with grep
- capability.
-
- Proto Drake
- Make function and method prototype files from drag-and-dropped C
- source files.
-
- Icon Elephant
- Tired of the Finder spontaneously rearranging your windows╒
- icons under mysterious circumstances, after you spent five minutes getting
- the icons just right? Drag-and-drop a folder on Icon Elephant to restore
- ╘remembered╒ icon positions on demand.
-
- Dragon Deity
- Create Dragonsmith source code and related files quickly and
- easily; check projects and their resource files for consistency,
- completeness, and general good health.
-
- THINK╩C Thief
- Drag-and-drop THINK╩C 5.0 projects to discover what files they
- contain, and more.
-
-
- ------------------------------------------------------
- DRAGON INSTANCE VARIABLES
- ------------------------------------------------------
-
- Most of the instance variables described below should normally not be
- altered by subclasses of Dragon. Instance variables whose values are set in
- ReadPrefs (from the ╘DrPr╒╩128 resource) are noted.
-
- abortProcessing
-
- Boolean abortProcessing;
-
- Don╒t change the value of this instance variable directly ╤ call
- StopProcessing instead
-
- This flag will be set to TRUE if a serious error prevents the current Open
- Documents from continuing, or if the user cancels processing by pressing
- Command╨period.
-
- acceptableTypes
-
- TypeListHndl acceptableTypes;
-
- Don╒t change the value of this instance variable or the data it points to
-
- This is a handle to a list of document types (taken from your dragon╒s
- ╘FREF╒ resources) that your dragon knows how to process.
-
- aeQueue
-
- AppleEventQueue *aeQueue;
-
- Don╒t change the value of this instance variable
-
- This is a reference to an instance of class AppleEventQueue, which is used
- to manage a simple FIFO queue of Open Documents events received while your
- dragon is processing documents from a previous event.
-
- appFile
-
- FSSpec appFile;
-
- Don╒t change the value of this instance variable
-
- This contains an FSSpec to your application ╤ it╒s set in the Dragon class╒s
- constructor and can be used in any way you want.
-
- appleMenu
-
- MenuHandle appleMenu;
-
- Don╒t change the value of this instance variable
-
- This is a handle to the standard Apple menu implemented by the Dragon class.
-
- appResFork
-
- short appResFork;
-
- Don╒t change the value of this instance variable
-
- This instance variable contains a refNum to the resource fork of your dragon
- ╤ it╒s the access path created by the system when the application is
- launched.
-
- Note: When running in the THINK╩C Debugger, appResFork is actually a refNum
- to the project resource file. The effect in either case is identical.
-
- autoQuit
-
- Boolean autoQuit;
-
- Will be set in ReadPrefs
-
- This instance variable determines whether your dragon will terminate after
- processing the first Apple event it receives ╤ DoOapp, DoOdoc, and DoPdoc
- all test the value in autoQuit. Also, because an auto-quit dragon won╒t
- have any use for menus, the Start method will call SetUpMenus only if
- autoQuit != FALSE.
-
- busyCursor
-
- CursHandle busyCursor;
-
- This is a handle to the watch cursor (not animated) that is displayed (by
- CursorBusy) when your dragon is processing documents in the foreground.
-
- Note: Cursor animation is planned for a later release of Dragonsmith.
-
- curDirDepth
-
- short curDirDepth;
-
- Don╒t change the value of this instance variable
-
- The depth at which your dragon is currently processing documents. A depth
- of 0 indicates that the current document was specified in an Open Documents
- event your dragon received. A depth of -1 indicates that the current
- document is located immediately inside a folder or disk specified in an Open
- Documents event.
-
- curDocFSS
-
- FSSpec *curDocFSS;
-
- Don╒t change the value of this instance variable; you can change the data to
- which it points
-
- Pointer to an FSSpec designating the current document. The data in
- *curDocFSS is meaningful only while your dragon is processing documents.
-
- curDocPB
-
- PBRecUnion *curDocPB;
-
- Don╒t change the value of this instance variable; you can change the data to
- which it points
-
- This is a pointer to a PBRecUnion designating the current document. A
- PBRecUnion is a union of the six parameter blocks used in making low-level
- File Manager calls. The data in *curDocPB is meaningful only while your
- dragon is processing documents. Your dragon is free to change, in the
- ProcessFile and ProcessDirectory methods, any of the data to which curDocPB
- points. If it does so, it can call SaveDocInfo to make the changes
- permanent and (optionally) refresh the Finder╒s display of the window
- containing the document in order to make the changes visible to the user.
-
- If you╒re unfamiliar with the low-level File Manager routines and their
- various parameter blocks, you can safely ignore curDocPB altogether ╤ or you
- can use the macros defined in Dragon.h and described in the section Macros
- to access fields in curDocPB without having to understand how the macros
- work.
-
- Warning: Use of these macros can be tricky. Make sure that you understand
- when it is and is not safe to use them.
-
- cursorRgn
-
- RgnHandle cursorRgn;
-
- This instance variable is used as a parameter to WaitNextEvent. The Dragon
- class sets it to NULL. Your dragon should allocate a region in cursorRgn if
- it uses mouse-moved events.
-
- dirDepthLimit
-
- short dirDepthLimit;
-
- Will be set in ReadPrefs
-
- The depth (a negative value) to which your dragon will look inside nested
- directories in search of documents to process. The depth of each of the
- documents drag-and-dropped on your dragon is 0, so if dirDepthLimit is 0,
- then your dragon will only see the documents specified in the Open Documents
- event.
-
- Warning: Recursive (but not infinitely recursive) directory scanning may
- occur if dirDepthLimit < 0 and resolveAliases╩==╩TRUE. For more
- information, read the section Automatic disk and folder opening above. Even
- if resolveAliases == FALSE, because of the danger of stack overflow your
- dragon should not set dirDepthLimit lower than about ╨50. (Every recursion
- of ProcessDocsInDirectory requires 70 bytes on the stack, so this would
- consume 3500 bytes.)
-
- dragonPrefs
-
- DragonPrefsRec **dragonPrefs;
-
- Don╒t change the value of this instance variable
-
- The values in dragonPrefs are read from the ╘DrPr╒ 128 resource (in
- ReadPrefs) and are used to set the following instance variables:
-
- filesOnly sleepValue[0..3]
-
- resolveAliases sleepTime
-
- followAliasChain dirDepthLimit
-
- autoQuit
-
- editMenu
-
- MenuHandle editMenu;
-
- Don╒t change the value of this instance variable
-
- This is a handle to the standard Edit menu implemented by the Dragon class.
-
- fileMenu
-
- MenuHandle fileMenu;
-
- Don╒t change the value of this instance variable
-
- This is a handle to the minimal File menu (containing a single Quit item)
- implemented by the Dragon class.
-
- filesOnly
-
- Boolean filesOnly;
-
- Will be set in ReadPrefs
-
- The value of filesOnly is tested only when all of the following are true:
-
- Ñ Your dragon has an ╘FREF╒ resource for the document type ╘fold╒ or ╘disk╒
-
- Ñ Your dragon encounters a directory at the maximum depth (curDirDepth ==
- dirDepthLimit)
-
- Ñ useCustomFilter == FALSE or the directory passes the CustomFilterDoc test
-
- Under these circumstances, ProcessDirectory will be executed only if
- filesOnly is FALSE. This instance variable should be set to TRUE if you
- want to ensure that ProcessDirectory will never be called. See the How to╔
- section for more information on what combination of values to use to achieve
- a particular drag-and-drop effect.
-
- Note: It doesn╒t make sense to add ╘FREF╒ resources for ╘disk╒ and ╘fold╒
- types, then set dirDepthLimit to 0 and filesOnly to TRUE.
-
- followAliasChain
-
- Boolean followAliasChain;
-
- Will be set in ReadPrefs
-
- This instance variable is only meaningful if resolveAliases == TRUE.
- Normally, followAliasChain should be TRUE ╤ if not, then an alias file at
- the beginning of an alias chain will only be resolved one step of the way
- rather than all the way to the original document.
-
- menusInstalled
-
- Boolean menusInstalled;
-
- Don╒t change the value of this instance variable
-
- This instance variable will be set to TRUE as soon as your dragon╒s menus
- have been installed. Several Dragon methods rely on the value of
- menusInstalled to avoid a crash.
-
- numAEsPending
-
- short numAEsPending;
-
- Don╒t change the value of this instance variable
-
- This is the number of outstanding Apple events tracked by the aeQueue
- object.
-
- preferences
-
- Preferences *preferences;
-
- Don╒t change the value of this instance variable
-
- This is a reference to an instance of class Preferences, used to manage the
- dragon╒s preferences.
-
- Note: If you don╒t want your dragon to use a preferences file, you should
- not alter (or delete) this object ╤ set the ╘STR ╒ 128 resource to "\p"
- instead (and delete the ╘FREF╒ for type prefsFileType). The preferences
- object is used to manage preferences, not just a preferences file.
-
- prefsFileType
-
- OSType prefsFileType;
-
- This is the file type of your dragon╒s preferences file. The System 7
- Finder supplies a generic icon for files of type ╘pref╒, and that╒s the
- value that Dragon uses.
-
- resolveAliases
-
- Boolean resolveAliases;
-
- Will be set in ReadPrefs
-
- The value of this instance variable determines whether your dragon will
- automatically resolve alias files that it encounters while processing
- documents from an ╘odoc╒ event. Normally, alias files will only be found
- inside a drag-and-dropped directory, when dirDepthLimit < 0 ╤ the Finder
- automatically resolves alias files before putting them in the event╒s list
- of documents. An Open Documents event sent by any other application,
- however, may contain references to alias files.
-
- Warning: You should not set resolveAliases = TRUE (in your dragon╒s
- constructor or in its ╘DrPr╒ 128 resource) unless either of these two
- conditions is true:
-
- Ñ Nothing ╘bad╒ will happen if your dragon processes the same file more
- than once.
-
- Ñ Your dragon can tell if it╒s already processed a file.
-
- One way to make sure you don╒t process the same file twice would be to call
- TickCount in your dragon╒s BeginProcessing method, keep the result in an
- instance variable, and store this value in a resource (say, ╘PTix╒ 128) in
- every file that╒s processed. Then a simple check (in CustomFilterDoc,
- probably) of this resource for each file your dragon gets will ensure that
- nothing gets processed twice. The only problem with this approach is that
- would slow things down considerably.
-
- Even if your dragon does not set resolveAliases = TRUE, there╒s no guarantee
- that it won╒t process the same file twice ╤ the user might well
- drag-and-drop a file and an alias to the same file simultaneously. You
- shouldn╒t worry too much about this possibility, since there╒s very little
- you can do about it.
-
- running
-
- Boolean running;
-
- Don╒t change the value of this instance variable directly ╤ call StopRunning
- instead
-
- This flag is TRUE as long as your dragon is running. It will be set to
- FALSE in StopRunning to cause your dragon to quit (by ╘falling╒ out of the
- main event loop in Run).
-
- runState
-
- short runState;
-
- Don╒t change the value of this instance variable
-
- The low two bits of this instance variable designate the current state of
- your dragon. The following masks can be used to read these flags:
-
- maskInBG 0x0001 Indicates the dragon is running in the background
-
- maskBusy 0x0002 Indicates the dragon is processing documents
-
- This instance variable is maintained for your dragon by the Dragon class╒s
- constructor and its BeginProcessing, EndProcessing, DoSuspend, and DoResume
- methods.
-
- signature
-
- OSType signature;
-
- Don╒t change the value of this instance variable
-
- This is your dragon╒s application signature. You should assign unique
- signatures to the dragons you create and register each with Apple.
-
- sleepTime
-
- long sleepTime;
-
- This instance variable is used as a parameter to WaitNextEvent to indicate
- the maximum number of ticks your dragon will relinquish to other processes.
- Its value is maintained by the Dragon class╒s constructor and its
- BeginProcessing, EndProcessing, DoSuspend, DoResume, and ReadPrefs methods.
-
- sleepValue[4]
-
- long sleepValue[4];
-
- Will be set in ReadPrefs
-
- The four values in this instance variable denote the possible values for
- sleepTime when indexed by the low two bits of runState.
-
- useCustomFilter
-
- Boolean useCustomFilter;
-
- Set useCustomFilter to TRUE if your dragon╒s CustomFilterDoc method is used
- to filter out unwanted documents.
-
-
- ------------------------------------------------------
- DRAGON METHODS
- ------------------------------------------------------
-
- Each method description is preceded by its declaration (from the body of the
- Dragon class declaration in Dragon.h). Many of the methods have
- restrictions on how a subclass should or should not override them. ╘Do not
- override╒ should not be taken as an absolute; it simply means that you
- should have a thorough understanding of what the method does in Dragon (and
- why) before you override it. There are a few more explicit warnings as well
- ╤ these should be taken a bit more seriously.
-
- Abort
-
- virtual void Abort (short errNum);
-
- Abort is called whenever a serious error occurs that prevents execution of
- the dragon application from continuing. This method displays an error alert
- terminates the program.
-
- Warning: Your dragon should be very careful about calling Abort ╤ in
- general, you should avoid calling it any time after the Start method has
- completed execution.
-
- AdjustMenusBusy
-
- virtual void AdjustMenusBusy (void);
-
- Call inherited::AdjustMenusBusy if you override this method
-
- This method disables any menu items that the user must not be able to select
- while the dragon is processing documents ╤ notably, Quit. It does not
- disable the Apple menu. If your dragon has any additional menus (or menu
- items), you should override this method to avoid leaving any dangerous items
- enabled while the dragon is ╥busy.╙
-
- AdjustMenusIdle
-
- virtual void AdjustMenusIdle (void);
-
- Call inherited::AdjustMenusIdle if you override this method
-
- This method is the converse of AdjustMenusBusy ╤ it restores any menu items
- that were disabled when the dragon began processing documents.
-
- BeginProcessing
-
- virtual void BeginProcessing (void);
-
- Call inherited::BeginProcessing if you override this method
-
- BeginProcessing is called by ProcessDroppings before any drag-and-dropped
- documents are processed. Its default behavior in Dragon is to disable any
- menu items that must not be called while processing is going on, then put up
- a ╥busy╙ cursor.
-
- CallMoreMasters
-
- virtual void CallMoreMasters (void);
-
- CallMoreMasters calls MoreMasters the number of times specified in the
- ╘MoMa╒ 128 resource (as described below) in order to allocate additional
- master pointers. The resource files provided in the folder ╘Template Files╒
- all contain a value of 0 in the ╘MoMa╒ 128 resource.
-
- CanProcessDoc
-
- virtual Boolean CanProcessDoc (void);
-
- Don╒t override
-
- CanProcessDoc checks to make sure that the file or directory specified in
- curDocFSS and curDocPB is of a type that could be drag-and-dropped on your
- dragon and applies any special filtering you╒ve specified with
- useCustomFilter and CustomFilterDoc.
-
- CursorBusy
-
- virtual void CursorBusy (void);
-
- This method changes the cursor to a watch (not animated) to show that the
- application is doing something.
-
- Note: Cursor animation is planned for a later release of Dragonsmith.
-
- CursorIdle
-
- virtual void CursorIdle (void);
-
- This method changes the cursor to show that the application is idle.
-
- CustomFilterDoc
-
- virtual Boolean CustomFilterDoc (void);
-
- Override if your dragon needs to perform any additional filtering of
- documents beyond that provided by the Dragon class
-
- The CustomFilterDoc method will be called by ProcessDoc if and only if
- useCustomFilter != FALSE. For example, if your dragon reads a C source file
- and produces a header file with prototypes for the functions and methods
- contained in it, then your CustomFilterDoc method will presumably filter out
- any file whose type is not ╘TEXT╒ or whose name doesn╒t end with ╥.c╙.
-
- Note: Your CustomFilterDoc method can go ahead and call one of a number of
- different document-handling methods, based on whatever criteria it chooses,
- and then return FALSE to fool ProcessDoc into thinking that the document
- shouldn╒t be processed at all. If your dragon does this, however, you
- should keep in mind that future versions of Dragonsmith may provide an
- else-clause in ProcessDoc that takes some action if (it believes that) a
- document could not be handled.
-
- DoAbout
-
- virtual void DoAbout (void);
-
- Override this method if you want your dragon to display a splash window.
-
- This method is executed when the user chooses the ╘About╔╒ item from the
- Apple menu. The default in the Dragon class is to do nothing.
-
- DoActivate
-
- virtual void DoActivate (EventRecord *theEvent);
-
- Override this method if your dragon has windows
-
- This method is called by DoEvent whenever an activate event occurs (when a
- window is being activated, not deactivated). Refer to Inside Macintosh
- Volume VI, pages 5╨14 to 5╨17 for a description of the ╘SIZE╒ resource╒s
- effect on activate events.
-
- DoAppleMenu
-
- virtual void DoAppleMenu (short itemNum);
-
- Do not override
-
- DoAppleMenu is called whenever the user chooses an item in the Apple menu.
-
- DoBusy
-
- virtual void DoBusy (void);
-
- You shouldn╒t have to override this method (since you can override
- ShowProgress instead); call inherited::DoBusy if you do
-
- This method is the ╥busy╙ counterpart of DoIdle ╤ it╒s called when your
- dragon is processing docs rather than when it has nothing to do. The Dragon
- class calls it (at the beginning of ProcessDoc) for each document to be
- processed; your dragon can make additional calls to DoBusy in order to yield
- CPU time to other processes and to let the user switch to another
- application or cancel the document processing. The Dragon class╒s DoBusy
- method calls ShowProgress and WaitNextEvent (in that order).
-
- Warning: Your dragon should not call DoBusy at any time when cancellation by
- the user, or a Quit Application event sent by another process, would cause
- problems. (It╒s up to you to determine what ╘problems╒ means╔)
-
- DoDeactivate
-
- virtual void DoActivate (EventRecord *theEvent);
-
- Override this method if your dragon has windows
-
- This method is called by DoEvent whenever an activate event occurs (when a
- window is being deactivated, not activated). Refer to Inside Macintosh
- Volume VI, pages 5╨14 to 5╨17 for a description of the ╘SIZE╒ resource╒s
- effect on activate events.
-
- DoDiskInsert
-
- virtual void DoDiskInsert (EventRecord *theEvent);
-
- Do not override
-
- This method is called by DoEvent whenever a disk insert event occurs.
- Dragon::DoDiskInsert handles the event in the usual way, calling DIBadMount
- to give the user a chance to initialize the disk if it╒s damaged or not yet
- initialized.
-
- DoEditMenu
-
- virtual void DoEditMenu (short itemNum);
-
- Override this method if you add any items to your dragon╒s File menu. Call
- inherited::DoEditMenu if the item chosen isn╒t one of the added items.
-
- This method is executed whenever the user selects an item in the Edit menu.
- Dragon::DoEditMenu implements the standard behavior of an Edit menu with
- Undo, Cut, Copy, Paste, and Clear items (plus a dividing line between Undo
- and Cut).
-
- DoEvent
-
- virtual void DoEvent (EventRecord *event);
-
- Do not override
-
- This is the main ╥switchboard╙ from which event handling is dispatched.
- Your dragon would have to override this method only if it wanted to treat
- keyDown and autoKey events differently.
-
- DoFileMenu
-
- virtual void DoFileMenu (short itemNum);
-
- Override this method if you add any items to your dragon╒s File menu. Call
- inherited::DoFileMenu if the item chosen isn╒t one of the added items.
-
- This method is executed whenever the user selects an item in the File menu.
- The default behavior in Dragon::DoFileMenu simply checks to see if the item
- chosen is the last item in the menu, and calls StopRunning if it is.
-
- Warning: If your File menu doesn╒t end with Quit, then you should override
- this method and not call inherited::DoFileMenu.
-
- DoHighLevelEvent
-
- virtual void DoHighLevelEvent (EventRecord *theEvent);
-
- Do not override
-
- This method is called by DoEvent whenever a high level event occurs. It
- calls AEProcessAppleEvent if it╒s an Apple event, or DoOtherHLEvent if it╒s
- not.
-
- DoIdle
-
- virtual void DoIdle (void);
-
- Override this method if your dragon does some periodic task(s) while nothing
- else is happening.
-
- DoIdle is called by Run each time WaitNextEvent returns no event (or a null
- event). It╒s the ╥idle╙ counterpart of DoBusy, described above.
-
- Note: When overriding this method, keep in mind that your DoIdle will be
- called only when your dragon is not processing any documents and no
- already-received Apple events are waiting to be processed. Your method can
- rely on these facts to make assumptions about the dragon╒s state.
-
- DoKeyDown
-
- virtual void DoKeyDown (EventRecord *theEvent);
-
- Call inherited::DoKeyDown if you override this method and your method
- doesn╒t handle the event
-
- This method is called by DoEvent whenever a keyDown or autoKey event occurs.
- It checks for command╨key combinations (those in the menus as well as
- ╨period).
-
- DoMenu
-
- virtual void DoMenu (long menuItemCode);
-
- Override this method if you add any menus to your dragon. Call
- inherited::DoMenu if the item chosen isn╒t in one of the added menus.
-
- DoMenu is called in response to a mouseDown in the menu bar or command-key
- menu equivalent.
-
- DoMouseDown
-
- virtual void DoMouseDown (EventRecord *theEvent);
-
- Override this method if your dragon has windows
-
- This method is called by DoEvent whenever a mouseDown event occurs.
-
- DoMouseUp
-
- virtual void DoMouseUp (EventRecord *theEvent);
-
- This method is called by DoEvent whenever a mouseUp event occurs. You may
- need to override this method if you override DoMouseDown.
-
- DoOapp
-
- virtual OSErr DoOapp (AppleEvent *theAppleEvent, AppleEvent *theReply,
- long╩refcon);
-
- This method is called when the user launches the dragon from the Finder by a
- means other than drag-and-drop (i.e., by double-click, select and open, or
- select and Cmd╨Down Arrow). The default DoOapp method in Dragon just checks
- to see if autoQuit ==╩TRUE and calls StopRunning if it is.
-
- DoOdoc
-
- virtual OSErr DoOdoc (AppleEvent *theAppleEvent, AppleEvent *theReply,
- long╩refcon);
-
- DoOdoc is called by the Apple event handler function HandleOdoc whenever the
- dragon receives an Open Documents (╘odoc╒) event. If the dragon is already
- processing an Apple event, it calls SuspendAEvent and returns. Otherwise,
- it gives the list of documents in the keyDirectObject parameter of the Open
- Documents event to ProcessDropping. Finally, it checks to see if autoQuit
- ==╩TRUE and calls StopRunning if it is.
-
- DoOSEvent
-
- virtual void DoOSEvent (EventRecord *theEvent);
-
- Override this method if your dragon handles mouse-moved events or maintains
- its own private scrap
-
- This method is called by DoEvent whenever an OS event occurs. It in turn
- calls DoSuspend or Doresume.
-
- DoOtherHLEvent
-
- virtual void DoOtherHLEvent (EventRecord *theEvent);
-
- Override this method if your dragon handles non-Apple event high level
- events
-
- This method is called by DoHighLevelEvent whenever a high level event that
- is not an Apple event occurs.
-
- DoPdoc
-
- virtual OSErr DoPdoc (AppleEvent *theAppleEvent, AppleEvent *theReply,
- long╩refcon);
-
- DoPdoc will be called if the user (in the Finder) selects a file that
- belongs to your dragon and chooses ╥Print╙ from the File menu. Very few
- dragons will need to override this method ╤ the default Dragon::DoPdoc
- merely returns an error. Like DoOapp and DoOdoc, it checks to see if
- autoQuit ==╩TRUE and calls StopRunning if it is.
-
- DoQuit
-
- virtual OSErr DoQuit (AppleEvent *theAppleEvent, AppleEvent *theReply,
- long╩refcon);
-
- DoQuit calls StopRunning, which will set running = FALSE to terminate the
- main event loop.
-
- DoResume
-
- virtual void DoResume (void);
-
- Override this method if your dragon needs to perform any additional actions
- when it moves to the background.
-
- DoResume is called whenever your dragon receives a resume event.
- Dragon::DoResume adjusts the values of runState and sleepTime and, if the
- dragon is busy processing documents, calls CursorBusy to show a busy cursor.
-
- DoSuspend
-
- virtual void DoSuspend (void);
-
- Override this method and call inherited::DoSuspend if your dragon needs to
- perform any additional actions when it moves to the background.
-
- DoSuspend is called whenever your dragon receives a suspend event.
- Dragon::DoSuspend adjusts the values of runState and sleepTime and, if the
- dragon is busy processing documents, calls CursorIdle to restore the
- standard arrow cursor.
-
- DoUpdateEvent
-
- virtual void DoUpdateEvent (EventRecord *theEvent);
-
- Override this method if your dragon has windows
-
- This method is called by DoEvent whenever an update event occurs.
-
- Dragon
-
- Dragon (void);
-
- This is the Dragon constructor, which is called when the gDragon object is
- created (in main), before the constructor (if there is one) for your
- subclass of Dragon.
-
- EndProcessing
-
- virtual void EndProcessing (void);
-
- Call inherited::EndProcessing if you override this method
-
- This method performs ╥housekeeping╙ tasks associated with the completion of
- document processing ╤ it sets sleepTime to the appropriate value and calls
- AdjustMenusIdle and CursorIdle.
-
- Error
-
- virtual void Error (short errNum);
-
- The Error method displays a very simple alert showing a brief message and
- the number passed in the errNum parameter.
-
- FindPrefsFile
-
- virtual Boolean FindPrefsFile (FSSpec *fss);
-
- Do not override
-
- This method looks for your dragon╒s preferences file (the name of which is
- specified in your dragon╒s ╘STR╩╘ 128 resource). It looks first in the same
- folder that contains your dragon, then in the Preferences folder within the
- System folder. If necessary, it calls MakePrefsFile to create a new file.
-
- Finish
-
- virtual void Finish (void);
-
- Call inherited::Finish if you override this method
-
- Finish is called by main after the Run method has ended. It╒s responsible
- for any last-minute ╥clean-up╙ ╤ close any open files, delete temporary
- files, remove trap patches, dispose of objects, etc. The default behavior
- in Dragon is to dispose of the preferences object, flush the Apple events
- queue (returning errors in the reply events of any pending Apple events),
- and dispose of the aeQueue object.
-
- Warning: If you override Finish, you must call inherited::Finish at the end
- of your method. If the code in Dragon::Finish is not executed, the current
- preferences will not be saved and there is a possibility (of unknown
- likelihood) that a crash will occur if there are any pending Apple events.
-
- FlushAEventQueue
-
- virtual void FlushAEventQueue (void);
-
- Do not override
-
- FlushAEventQueue is called by Finish when there any pending Apple events.
- It asks the aeQueue object for each of the pending Apple events, then calls
- AEResumeTheCurrentEvent with a pointer to the ReturnEventNotHandled
- function. This tells the sender of each pending Apple event that the event
- wasn╒t handled ╤ since Finish is the last code that is executed, there╒s no
- possibility of handling any events at this point.
-
- InitAppleEvents
-
- virtual void InitAppleEvents (void);
-
- Override this method if your dragon handles any additional Apple events
-
- InitAppleEvents installs handlers for the four required Apple events, and
- calls MakeAEQObject.
-
- InitMac
-
- virtual void InitMac (void);
-
- Override this method and call inherited::InitMac (at the beginning of your
- method) if your dragon requires more than the usual initializations.
-
- InitMac initializes the usual system software managers. Dragon::InitMac
- calls InitGraf, InitFonts, InitWindows, InitMenus, TEInit, InitDialogs, and
- InitCursor (in that order).
-
- InitMem
-
- virtual void InitMem (void);
-
- Override this method if you want to increase the amount of memory allotted
- to your dragon╒s stack
-
- InitMem enlarges your dragon╒s application zone to its maximum size and
- calls CallMoreMasters.
-
- InitMilieu
-
- virtual void InitMilieu (void);
-
- Do not override this method ╤ add to the ╘GChk╒ resource instead
-
- InitMilieu checks your dragon╒s run-time environment against the
- specifications in the ╘GChk╒ 128 resource (as described below), and calls
- Abort with an appropriate error code if the run-time environment is not
- sufficient to run your dragon. Otherwise, it calls InitAppleEvents.
-
- InitPrefs
-
- virtual void InitPrefs (void);
-
- Do not override
-
- This method creates and initializes the preferences object, asks
- FindPrefsFile to look for a preferences file, and (if one is found or
- created) tells the preferences object to use that file. If the preferences
- file had to be created, then the appropriate preferences resources will be
- copied to it from the dragon╒s application file. InitPrefs ends by calling
- ReadPrefs to read in the preferences from the file╒s resources.
-
- InteractWithUser
-
- virtual Boolean InteractWithUser (long timeOut);
-
- Do not override
-
- Your dragon should call this method if it needs to interact with the user
- (by putting up a dialog, for example) while it╒s processing documents.
- InteractWithUser calls the Toolbox routine AEInteractWithUser using an idle
- function (CallWaitIdle, described below) that ensures that events will be
- processed normally while idling.
-
- The timeOut parameter is the number of ticks your dragon is willing to wait
- for the user to bring the dragon to the foreground. A reasonable value for
- timeOut might fall between 600 and 7200 ticks (10 seconds and 2 minutes).
-
- IsPrefsFile
-
- virtual Boolean IsPrefsFile (FSSpec *fss);
-
- Do not override
-
- This method checks the file specified by fss to make sure it has the proper
- creator and type to be your dragon╒s preferences file.
-
- Note: IsPrefsFile does not test the validity of the file╒s resources ╤ that
- responsibility falls to the VerifyResources method of your subclass of the
- Preferences class, if you choose to make one.
-
- MakeAEQObject
-
- virtual AppleEventQueue *MakeAEQObject (void);
-
- Override this method if you implement a subclass of AppleEventsQueue
-
- MakeAEQObject creates, and returns a reference to, an instance of class
- AppleEventsQueue(or of a subclass of AppleEventsQueue, if you override this
- method).
-
- MakePrefsFile
-
- virtual Boolean MakePrefsFile (FSSpec *fss);
-
- Do not override
-
- This method creates a new preferences file, as specified by fss. It does
- not add any resources to the file.
-
- MakePrefsObject
-
- virtual Preferences *MakePrefsObject (void);
-
- Override this method if you implement a subclass of Preferences
-
- MakePrefsObject creates, and returns a reference to, an instance of class
- Preferences (or of a subclass of Preferences, if you override this method).
-
- ProcessDirectory
-
- virtual void ProcessDirectory (void);
-
- Your dragon should override this method if it processes directories (folders
- and volumes) themselves rather than their contents (files and other
- directories).
-
- ProcessDirectory will be executed only when ╤
-
- ( filesOnly == FALSE
- && curDocIsDirectory // it's a folder or disk
- && curDirDepth == dirDepthLimit
- && CanProcessDoc () )
-
- Here are some examples of the functionality of dragons that would need to
- override ProcessDirectory:
-
- Ñ Show information about a disk [presumably more that what the Finder╒s
- ╥Get Info╙ gives you]
- Ñ Scan a folder (or folders) for new files dropped in it (or them), then
- call ProcessFile for each such file (for example, to monitor incoming mail
- or expand files [this is essentially what DownLine does]
- Ñ Copy the full paths of selected directories (and files) to the clipboard
- [this is what FilePaths does]
-
- ProcessDoc
-
- virtual void ProcessDoc (void);
-
- Don╒t override
-
- This method (which should normally not be overridden) is the ╥bottleneck╙
- through which all documents must pass before they can be processed. It
- begins by checking to see that the document specified by curDocFSS and
- curDocPB (both of which are valid at this point) is of a kind that could be
- drag-and-dropped on your dragon, then applies any special filtering that you
- may have set up in CustomFilterDoc. If the document meets those
- requirements, ProcessDoc passes it as follows:
-
- Ñ If the document is a file belonging to your dragon (curDocIsFile &&
- curDocCreator ==╩this->signature), then it╒s passed to ProcessOwnedFile.
- Ñ If the document is a file that does not belong to your dragon, then it╒s
- passed to ProcessFile ╤ this is the usual case.
- Ñ If the document is a folder or volume and the maximum level of folder
- opening (see the descriptions of curDirDepthLimit and dirDepthLimit in the
- Instance Variables section) has not yet been reached, then it╒s passed to
- ProcessDocsInDirectory, which will process the documents inside the folder
- (or volume).
- Ñ If the document is a folder or volume at the maximum level of folder
- opening, and if your dragon sets filesOnly = FALSE, then it will be passed
- to ProcessDirectory.
-
- ProcessDocsInDirectory
-
- virtual void ProcessDocsInDirectory (short vRefNum, long dirID);
-
- Don╒t override
-
- This method looks through the current directory and, for each thing it finds
- there, sets up curDocFSS and curDocPB and calls ProcessDoc.
-
- ProcessDroppings
-
- virtual OSErr ProcessDroppings (AEDescList *docList);
-
- ProcessDroppings loops through the documents that were drag-and-dropped on
- your application and calls ProcessDoc for each one after setting up
- curDocFSS and curDocPB. Alias files are resolved here (if resolveAliases !=
- FALSE). ProcessDroppings calls BeginProcessing before handling the first
- document and EndProcessing after the last.
-
- ProcessFile
-
- virtual void ProcessFile (void);
-
- Override except in unusual cases
-
- ProcessFile is the heart of any typical sub-class of Dragon. Unless your
- dragon only handles volumes or folders, you will certainly need to override
- this method ╤ this is where the actual work is done (or the methods that do
- the work are called).
-
- ProcessOwnedFile
-
- virtual void ProcessOwnedFile (void);
-
- Override if your dragon creates any special file types (other than
- preferences files) and treats them differently than it does files which it
- didn╒t create
-
- The default behavior for ProcessOwnedFile is to check if the file designated
- by curDocFSS and curDocPB is a preferences file and, if it is, to use the
- preferences found in it.
-
- ReadPrefs
-
- virtual void ReadPrefs (void);
-
- Call inherited::ReadPrefs if you override this method
-
- The purpose of this method is to read in settings from the dragon╒s
- preferences file (from the resources specified in its ╘PrRo╒ 128 resource ╤
- see description below) and change the appropriate instance variables
- accordingly. It should call preferences->GetPrefResource for each
- preferences resource. The Dragon::ReadPrefs method sets the following
- instance variables:
-
- filesOnly sleepValue[0..3] resolveAliases sleepTime
- followAliasChain dirDepthLimit autoQuit
-
- You should check to see if preferences->GetPrefResource returns NULL when
- overriding this method, and in any other method that might rely on a
- preferences resource being in memory ╤ an incomplete preferences file should
- never cause a crash. See the code in the How do I╔ section above for an
- example.
-
- Note: Remember that your dragon╒s preferences will come from the application
- file if no preferences file could be found or created.
-
- ResumeAEvent
-
- virtual void ResumeAEvent (void);
-
- Do not override
-
- This method is called by Run whenever WaitNextEvent doesn╒t report an event
- and one or more previously received Apple events are pending. ResumeAEvent
- asks the aeQueue object for the oldest pending Apple event, then calls
- AEResumeTheCurrentEvent to handle the event normally.
-
- Run
-
- virtual void Run (void);
-
- Do not override
-
- Run contains the main event loop, which calls either DoEvent, DoIdle, or (if
- there are any pending Apple events) ResumeAEvent. The loop terminates only
- when this->running is set to FALSE (by StopRunning).
-
- SaveDocInfo
-
- virtual void SaveDocInfo (Boolean refreshFinder);
-
- Call SaveDocInfo right after you change one or more of the following values:
-
- curFileType curFileCreator curFileFlags
-
- curDocCreated curDocModified
-
- or any other field in *curDocPB that PBSetCatInfo takes as input.
-
- Note: To rename the current document, you should call FSpRename (rather than
- just changing *curDocName) after calling SaveDocInfo (TRUE).
-
- Warning: If your dragon makes any low-level File Manager calls that leave
- garbage in any fields in *curDocPB that PBSetCatInfo takes as input, then it
- should do so after calling this method, or save and restore those values, or
- refrain from calling SaveDocInfo at all. Table 2 contains a partial list of
- low-level File Manager calls that leave garbage in fields that PBSetCatInfo
- uses.
-
- <Table 2 omitted>
-
- SetUpMenus
-
- virtual void SetUpMenus (void);
-
- If you override this method, call inherited::SetUpMenus at the beginning of
- your method and DrawMenuBar at the end
-
- SetUpMenus is called by Start (unless autoQuit != FALSE). It initializes
- your dragon╒s menus, including (by default) a standard Apple Menu, a File
- menu with just one item (Quit), and an Edit menu with the five basic editing
- commands (Undo, Cut, Copy, Paste, and Clear).
-
- ShowProgress
-
- virtual void ShowProgress (void);
-
- For future compatibility, you should call inherited::DoBusy if you override
- this method
-
- Override ShowProgress if you want your dragon to give the user some visual
- indication of the progress it╒s making on processing the documents the user
- drag-and-dropped on it. If your dragon doesn╒t look inside directories
- (i.e., if dirDepthLimit == 0) then you might want to show a progress bar
- similar to the one the Finder puts up while copying files. If it does look
- in directories, then you could display the name of each document as it╒s
- processed.
-
- Warning: ShowProgress is called for every file, folder, or disk
- drag-and-dropped on your dragon (or sent in an Open Documents event from a
- source other than the Finder) ╤ even ones that your dragon can╒t (for
- whatever reason) process. Keep this mind if you want to display the names
- only of documents as they╒re processed ╤ you╒ll need to override
- ProcessFile, ProcessDirectory, or ProcessDocsInDirectory (or some
- combination of those three) instead.
-
- Also, your DoBusy method should not change *curDocFSS or *curDocPB in any
- way.
-
- Note: Implementing a movable modal window (as an instance of a class that
- you can override) is high on the list of future plans for Dragonsmith, but
- adding it to Dragon will probably require significant changes to ProcessDoc
- and ShowProgress. If you override either of these methods, keep in mind
- that your code may have to be changed later for compatibility with new
- releases of Dragonsmith.
-
- Start
-
- virtual void Start (void);
-
- Start initializes your dragon╒s run-time environment ╤ memory, menus,
- preferences, events, etc.
-
- StopProcessing
-
- virtual void StopProcessing (OSErr err);
-
- Call inherited::StopProcessing if you override this method
-
- StopProcessing should be called whenever an error occurs that is serious
- enough that processing should be stopped (including cancellation by the
- user). The parameter should specify the reason for stopping.
- Dragon::StopProcessing just sets abortProcessing = TRUE; your Dragon
- subclass can display an error message or otherwise indicate that something
- went wrong (but it should stop ╥quietly╙ if the user generated a cancel
- event).
-
- StopRunning
-
- virtual void StopRunning (void);
-
- This method sets running = FALSE, after calling StopProcessing if your
- dragon is currently processing an Open Documents event. The dragon╒s main
- event loop will terminate as soon as control is returned to Run.
-
- SuspendAEvent
-
- virtual OSErr SuspendAEvent (AppleEvent *event, AppleEvent *reply,
- AEHandlerFunc╩*handler, long refcon);
-
- Do not override
-
- SuspendAEvent is called by ProcessOdoc any time your dragon receives an Open
- Documents event while processing a previously received one. SuspendAEvent
- asks the aeQueue object to add the event to its queue, then calls the
- Toolbox routine AESuspendTheCurrentEvent to let the System know the event
- isn╒t being handled.
-
- Warning: Be very careful if you decide to override this method. Any
- application that receives an Apple event while processing one received
- earlier must either call AESuspendTheCurrentEvent or interrupt the first
- event until handling of the second is completed. It appears that dividing
- CPU time between the handling of several Apple events (without calling
- AESuspendTheCurrentEvent and AEResumeTheCurrentEvent at the appropriate
- times) will cause the system to grow very confused!
-
- WaitIdle
-
- virtual Boolean WaitIdle (EventRecord *theEvent, long *sleep,
- RgnHandle╩*mouseRgn);
-
- WaitIdle will be called whenever your dragon gets an update, activate, null,
- or OS event while it╒s waiting for AEInteractWithUser to return ╤ i.e.,
- while it waits for the user to bring it to the foreground. The default
- behavior in the Dragon class is to let the main event handler, DoEvent, pass
- the buck. Please note that recursion is not a possibility unless you do
- some very strange overriding of the DoActivate, DoUpdateEvent, DoOSEvent,
- DoSuspend, or DoResume methods.
-
-
- ------------------------------------------------------
- RESOURCES
- ------------------------------------------------------
-
- This section briefly describes all of the resources that should be present
- in your dragon╒s project resource file (with the exception of the ╘SIZE╒ and
- signature resources, which THINK╩C will add to the built application). All
- of the project resource files provided with Dragonsmith╩1.1 contain these
- resources. The best way to gain a full understanding of the
- Dragonsmith-specific resources is to view them in ResEdit and look for
- mentions of them in the Dragonsmith source code.
-
- Dragonsmith resources
-
- The following resources have Dragonsmith-specific functions:
-
- ALRT 129 Alert used by Dragon::Error.
-
- DITL 129 Dialog item list for use with ╘ALRT╒ 129.
-
- DrPr 128 Dragon class preferences. The following Dragon instance variables
- are all copied from values in this resource:
- autoQuit resolveAliases followAliasChain
- sleepValue[0..3] filesOnly dirDepthLim
- If your dragon sets any of these instance variables in its constructor, then
- you should put the same values into the fields in your project resource
- file╒s ╘DrPr╒ 128 resource. Forgetting to do so can cause tremendous
- frustration.
-
- GChk 128 A list of Gestalt calls and the values that they should return. InitMilieu
- passes this resource to the GestaltBatchCheck function, which returns noErr if the
- run-time environment is sufficient for the dragon to function properly. Each entry
- in the list has the following structure:
- typedef struct {
- OSType selector; // Selector to call Gestalt with
- short compOp; // Type of comparison to make
- short failureError; // Error to return if check fails
- long compValue; // Check Gestalt result against this
- }
- Possible values for the compOp field are listed in the file GestaltUtils.h.
-
- MENU 128 Apple menu,
- 129 File menu,
- 130 Edit menu.
-
- MoMa 128 Number of times to call MoreMasters.
-
- PrRo 128 Preferences roster ╤ a list of the dragon╒s preferences resources.
- You must add to this list whenever you add a new preferences resource.
-
- STR 128 Name of the dragon╒s preferences file. To prevent a preferences
- file from being created, put a null string in this resource and delete the
- ╘FREF╒ resource for the type designated by the instance variable
- prefsFileType.
-
- ResEdit templates for the Dragonsmith-specific resources are available in
- the ╘Dragonsmith TMPLs╒ file ╤ keep this file open whenever viewing or
- editing them.
-
- Finder-related resources
-
- The following resoures are used by the Finder to correctly launch an
- application, control drag-and-drop onto it, and display its icons and
- information in the Finder:
-
- <signature> 0 The type of this resource should be the same as your
- application╒s signature (set via the ╘Set Project Type╔╒ dialog in THINK╩C).
- It contains a copyright string for the application.
-
- BNDL 128 This resource coordinates an application╒s Finder-related
- resources. You can ResEdit 2.1╒s ╘BNDL╒ editor to modify this resource as
- well as the ╘FREF╒, signature, and icon resources.
-
- FREF 128, etc. These resources designate the types of files your dragon can
- process. Make sure you have one for every document type your dragon is
- capable of processing, plus one (╘APPL╒) for the application itself, plus
- one for the file type designated by the instance variable prefsFileType
- (normally ╘pref╒) if your dragon creates a preferences file.
-
- Use the values ╘fold╒ and ╘disk╒ to allow drag-and-drop of folders and
- volumes (respectively) onto your dragon.
-
- Use the value ╘****╒ to specify that your dragon can process files (not
- folders or volumes) of any type.
-
- hfdr
- styl
- TEXT 128 These three resources in combination provide Ballon Help for your
- dragon╒s icon in the Finder. Delete all three if you don╒t want this
- feature.
-
- icl4,
- icl8,
- ICN#,
- ics#,
- ics4,
- ics8 Icons for your dragon╒s application and files.
-
- SIZE ╨1 The SIZE resource must be set up correctly for an application to
- accept Apple events, and the Dragon class relies on Apple events ╤ if a
- dragon can╒t get an Open Documents event, it won╒t do anything. Don╒t put
- your own ╘SIZE╒ resource in the .rsrc file ╤ use the SIZE settings available
- by choosing ╘Set Project Type╔╒ from THINK╩C╒s Project menu.
-
- vers 1 This is the ╘true╒ version string which appears in the Get Info╔
- window
-
- vers 2 This string appears directly under your application╒s name in its Get
- Info╔ window in the Finder. The dragons provided with Dragonsmith use the
- words ╘a Dragon sub-species╒ in this string, but you╒re not required to
- follow this convention in your own dragons.
-
- Inside Macintosh, Volume VI has an extensive description of Finder-related
- resources on pages 9-5 to 9-24 and 9-34 to 9-35 ╤ read it for more
- information on these resources. Keep in mind that many of these resources
- must be modified before your dragon╒s first built version, or you may have
- to rebuild the desktop to make the Finder╒s behavior reflect any changes in
- them.
-
-
-